/*
 * Copyright (c) 2010, Thiago Campos Viana.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *     * Neither the name of Thiago Campos Viana nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package kernel.gamecode;

import java.net.InetAddress;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import lib.db.DataBase;

/**
 * Player class
 * @author Thiago Campos Viana
 */
public class Player extends Character {

    /**
     * The id counter of players online.
     * <p>
     * When a player log, it is incremented and player session id
     * <br >
     * idCount value is asssigned to player session id
     */
    public static int idCount=0;
    /**
     * The item in the player's left hand
     */
    public Item leftHand;
    /**
     * The item in the player's right hand
     */
    public Item rightHand;
    /**
     * The item in the player's head
     */
    public Item head;
    /**
     * Player's legs
     */
    public Item legs;
    /**
     * Player's boots
     */
    public Item boots;
    
    
    


    /**
     * Player's total experience points
     */
    public int exp;
    

    /**
     * Player's InetAddress
     */
    public InetAddress address;

    /**
     *
     * @param region
     * @param name
     * @param address
     */
    public Player(ResultSet rs, InetAddress address) {
        
        Player.idCount+=1;
        this.id=Player.idCount;
        try {
            this.layer=(byte)rs.getInt("layer");
            this.name = rs.getString("login");
            this.region = GameLoopThread.getInstance().map.regions.get(((byte)rs.getInt("region")));
            x=(short)rs.getInt("x");
            y=(short)rs.getInt("y");
            if(x==0 && y==0 && layer==0)
            {
                x = 2;
                y = 2;
            }
        } catch (SQLException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        }
        this.address = address;

        
        

        //rightHand = new Item(100);


        //leftHand = new Item(10);
        



    }



    /**
     *
     * @return
     */
    @Override
    public byte[] update() {
        
        checkTile();
        checkStatus();
        return getBytes();

    }

    /**
     *
     * @param direction
     */
    public void move(byte direction) {
        
        /* Directions
         * 0 - stay
         * 1 - up
         * 2 - right
         * 3 - down
         * 4 - left
         */

        if (direction == 0) {
            return;
        }

        /* Tile Types:
         * 0 - walkable
         * 1 - blocked
         * 2 - blocked by GameObject
         * 3 - UpStairs up
         * 4 - UpStairs right
         * 5 - UpStairs down
         * 6 - UpStairs left
         * 7 - DownStairs up
         * 8 - DownStairs right
         * 9 - DownStairs down
         * 10 - DownStairs left
         * 11 - Blocked to NPCS and Monsters
         * 12 - Closed Door
         * 13 - Openned Door
         * 14 - Trap
         * 15 - Safe Tile - players não se atacam
         */

        short newX = x;
        short newY = y;

        switch (direction) {
            case 1:
                newY--;
                break;
            case 2:
                newX++;
                break;
            case 3:
                newY++;
                break;
            case 4:
                newX--;
                break;
            default:
                break;

        }
        // verifica se tile é bloqueado, bloqueado por algum jogador, ou é porta fechada.
        if (region.tileMap[layer][newY][newX] != 1 && region.tileMap[layer][newY][newX] != 2 && region.tileMap[layer][newY][newX] != 12) {
            if (region.tileMap[layer][y][x] == 2) {
                region.tileMap[layer][y][x] = 0;
            }
            x = newX;
            y = newY;
            if (region.tileMap[layer][y][x] == 0) {
                region.tileMap[layer][y][x] = 2;
            }

        } else if (region.tileMap[layer][newY][newX] == 12) {
            // verifica se é porta fechada e se o player está com a chave da porta na mão
            Iterator<Door> doors = region.doors.iterator();
            Door door;
            while (doors.hasNext()) {
                door = doors.next();
                
                if (door.x == newX && door.y == newY && door.layer == layer) {

                        if ((leftHand!=null && door.keyId == leftHand.id) || (rightHand != null && door.keyId == rightHand.id)) {
                            if (region.tileMap[layer][y][x] == 2) {
                                region.tileMap[layer][y][x] = 0;
                            }
                            x = newX;
                            y = newY;
                        }

                }

            }

        }



    }

    public void save(){
        System.out.println("aaa");
        String sql="update player set x='"+x+"', y='"+y+"', layer='"+layer+"' "
                +" where login = '"+name+"'";
        System.out.println(sql);
        DataBase.getInstance().execute(sql);
    }

    /**
     *
     */
    public void checkTile() {
        /* Tile Types:
         * 0 - walkable
         * 1 - blocked
         * 2 - blocked by GameObject
         * 3 - UpStairs up
         * 4 - UpStairs right
         * 5 - UpStairs down
         * 6 - UpStairs left
         * 7 - DownStairs up
         * 8 - DownStairs right
         * 9 - DownStairs down
         * 10 - DownStairs left
         * 11 - Blocked to NPCS and Monsters
         * 12 - Closed Door
         * 13 - Openned Door
         * 14 - Trap
         */

        switch (region.tileMap[layer][y][x]) {
            case 0:
            case 1:
            case 2:
                break;
            case 3:
                layer++;
                y--;
                break;
            case 4:
                layer++;
                x++;
                break;
            case 5:
                layer++;
                y--;
                break;
            case 6:
                layer++;
                x--;
                break;
            case 7:
                layer--;
                y--;
                break;
            case 8:
                layer--;
                x++;
                break;
            case 9:
                layer--;
                y--;
                break;
            case 10:
                layer--;
                x--;
                break;
        }

    }

    /**
     *
     */
    public void checkStatus() {
    }


    /**
     *
     * @param exp
     */
    public void train(int exp){

        experience+=exp;
        int nextLevel = (level-1)*20 + (level*7) + level*level*level - level*level;

        if( experience>=nextLevel ){
            level++;
            attack+=4;
            agility+=2;
            maxMP++;
            maxHP+=4;
            //hp=maxHP;
            train(0);
        }


    }
}
